﻿using CacheManager.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Shake.Framework.Services
{
    public interface IShakeCacheManager<T>
    {
        T AddOrUpdate(CacheItem<T> addItem, Func<T, T> updateValue, int maxRetries);

        T AddOrUpdate(CacheItem<T> addItem, Func<T, T> updateValue);
        T AddOrUpdate(string key, string region, T addValue, Func<T, T> updateValue, int maxRetries);
        T AddOrUpdate(string key, T addValue, Func<T, T> updateValue, int maxRetries);
        T AddOrUpdate(string key, string region, T addValue, Func<T, T> updateValue);

        T AddOrUpdate(string key, T addValue, Func<T, T> updateValue);

        IEnumerable<CacheManager.Core.Internal.BaseCacheHandle<T>> CacheHandles { get; }

        IReadOnlyCacheManagerConfiguration Configuration { get; }

        T GetOrAdd(string key, string region, Func<string, string, T> valueFactory);

        T GetOrAdd(string key, Func<string, T> valueFactory);

        T GetOrAdd(string key, string region, T value);

        T GetOrAdd(string key, T value);

        string Name { get; }

        event EventHandler<CacheManager.Core.Internal.CacheActionEventArgs> OnAdd;

        event EventHandler<CacheManager.Core.Internal.CacheClearEventArgs> OnClear;

        event EventHandler<CacheManager.Core.Internal.CacheClearRegionEventArgs> OnClearRegion;

        event EventHandler<CacheManager.Core.Internal.CacheActionEventArgs> OnGet;

        event EventHandler<CacheManager.Core.Internal.CacheActionEventArgs> OnPut;

        event EventHandler<CacheManager.Core.Internal.CacheActionEventArgs> OnRemove;

        event EventHandler<CacheManager.Core.Internal.CacheActionEventArgs> OnUpdate;

        bool TryGetOrAdd(string key, string region, Func<string, string, T> valueFactory, out T value);

        bool TryGetOrAdd(string key, Func<string, T> valueFactory, out T value);
        bool TryUpdate(string key, string region, Func<T, T> updateValue, int maxRetries, out T value);

        bool TryUpdate(string key, Func<T, T> updateValue, int maxRetries, out T value);

        bool TryUpdate(string key, string region, Func<T, T> updateValue, out T value);

        bool TryUpdate(string key, Func<T, T> updateValue, out T value);

        T Update(string key, string region, Func<T, T> updateValue, int maxRetries);

        T Update(string key, Func<T, T> updateValue, int maxRetries);

        T Update(string key, string region, Func<T, T> updateValue);

        T Update(string key, Func<T, T> updateValue);

        bool Add(CacheItem<T> item);

        bool Add(string key, T value, string region);
        bool Add(string key, T value);

        void Clear();

        void ClearRegion(string region);

        bool Exists(string key, string region);

        bool Exists(string key);
        void Expire(string key, string region, TimeSpan slidingExpiration);
        void Expire(string key, TimeSpan slidingExpiration);

        void Expire(string key, string region, DateTimeOffset absoluteExpiration);

        void Expire(string key, DateTimeOffset absoluteExpiration);
        void Expire(string key, string region, ExpirationMode mode, TimeSpan timeout);
        void Expire(string key, ExpirationMode mode, TimeSpan timeout);

        TOut Get<TOut>(string key, string region);
        TOut Get<TOut>(string key);

        T Get(string key, string region);
        T Get(string key);
        CacheItem<T> GetCacheItem(string key, string region);
        CacheItem<T> GetCacheItem(string key);

        void Put(CacheItem<T> item);

        void Put(string key, T value, string region);

        void Put(string key, T value);

        bool Remove(string key, string region);

        bool Remove(string key);
        void RemoveExpiration(string key, string region);
        void RemoveExpiration(string key);

        T this[string key, string region] { get; set; }

        T this[string key] { get; set; }

        void Dispose();
    }
}
